#ifndef __Collections_EqualityComparer_H__
#define __Collections_EqualityComparer_H__

///<summary>
/// EqualityComparer<T>
///</summary>
//+ requires: Collections_IEqualityComparer(T)
#define Collections_EqualityComparer(T) bindT(Collections_EqualityComparer,T)
#define Declare_Collections_EqualityComparer(T, Ti) \
	enum { \
		_Collections_EqualityComparer_##T##VIndex_Equals, \
		_Collections_EqualityComparer_##T##VIndex_GetHashCode, \
		_Collections_EqualityComparer_##T##VIndex_IndexOf, \
		_Collections_EqualityComparer_##T##VIndex_LastIndexOf, \
		_Collections_EqualityComparer_##T##VIndexNext, \
	}; \
	public abstract_ classTV(Collections_EqualityComparer,T,System_Object,classInterface(Collections_IEqualityComparer(T)), \
		public abstractT(Collections_EqualityComparer,T,bool,Equals, Ti x, Ti y); \
		public abstractT(Collections_EqualityComparer,T,int_,GetHashCode, Ti obj); \
		internal virtualT(Collections_EqualityComparer,T,int_,IndexOf, Ti array[], Ti value, int_ startIndex, int_ count); \
		internal virtualT(Collections_EqualityComparer,T,int_,LastIndexOf, Ti array[], Ti value, int_ startIndex, int_ count); \
	,); \
	Declare_DefaultCtorT(protected,Collections_EqualityComparer,T) \
	public static_ Collections_EqualityComparer(T) *spaceT(Collections_EqualityComparer,T,getDefault)();

#define Implement_Collections_EqualityComparer(T, Ti) \
	/*[ IndexOf ]*/ \
	internal int_ spaceT(_ec_,T,IndexOf)(Collections_EqualityComparer(T) *t, Ti array[], Ti value, int_ startIndex, int_ count) \
	{ \
		int_ i; \
		int_ num = startIndex + count; \
		for (i = startIndex; i < num; i++) \
		{ \
			if (vcallT(Collections_EqualityComparer,T,t,Equals, array[i], value)) \
			{ \
				return i; \
			} \
		} \
		return -1; \
	} \
	\
	/*[ LastIndexOf ]*/ \
	internal int_ spaceT(_ec_,T,LastIndexOf)(Collections_EqualityComparer(T) *t, Ti array[], Ti value, int_ startIndex, int_ count) \
	{ \
		int_ i; \
		int_ num = (startIndex - count) + 1; \
		for (i = startIndex; i >= num; i--) \
		{ \
			if (vcallT(Collections_EqualityComparer,T,t,Equals, array[i], value)) \
			{ \
				return i; \
			} \
		} \
		return -1; \
	} \
	\
	/*[ Equals ] */ \
	private_ bool spaceT(_ec_,T,Equals)(Collections_EqualityComparer(T) *t, object x, object y) \
	{ \
		if (x == y) \
        { \
            return true; \
        } \
        if ((x != null) && (y != null)) \
        { \
			if (is(x,Ti) && is(y,Ti)) \
            { \
				return vcallT(Collections_EqualityComparer,T,t,Equals, __unboxT(Ti,x), __unboxT(Ti,y)); \
            } \
			throw(ArgumentException,InvalidArgumentForComparison); \
        } \
        return false; \
	} \
	/*[ GetHashCode ] */ \
	private_ int_ spaceT(_ec_,T,GetHashCode)(Collections_EqualityComparer(T) *t, object obj) \
	{ \
        if (obj != null) \
        { \
            if (is(obj,Ti)) \
            { \
                return vcallT(Collections_EqualityComparer,T,t,GetHashCode, __unboxT(Ti,obj)); \
            } \
			throw(ArgumentException,InvalidArgumentForComparison); \
        } \
        return 0; \
	} \
	Implement_TypeTV(Collections_EqualityComparer,T,System_Object,typeInterface(Collections_IEqualityComparer(T)), \
		vtable[_Collections_EqualityComparer_##T##VIndex_IndexOf] = (System_ObjectVector)&spaceT(_ec_,T,IndexOf); \
		vtable[_Collections_EqualityComparer_##T##VIndex_LastIndexOf] = (System_ObjectVector)&spaceT(_ec_,T,LastIndexOf); \
		vtable = t->Collections_IEqualityComparer(T).__vtable; \
		vtable[_Collections_IEqualityComparer_##T##VIndex_Equals] = (System_ObjectVector)&spaceT(_ec_,T,Equals); \
		vtable[_Collections_IEqualityComparer_##T##VIndex_GetHashCode] = (System_ObjectVector)&spaceT(_ec_,T,GetHashCode); \
	) \
	Implement_DefaultCtorT(Collections_EqualityComparer,T,System_Object) \
	static private static_ Collections_EqualityComparer(T) *spaceT(Collections_EqualityComparer,T,s_defaultComparer) = nullT(Collections_EqualityComparer(T)*); \
	\
	/*[ CreateComparer ]*/ \
	private static_ Collections_EqualityComparer(T) *spaceT(Collections_EqualityComparer,T,CreateComparer)() \
	{ \
		return nullT(Collections_EqualityComparer(T)*); \
	} \
	\
	/*[ Default ]*/ \
	public static_ Collections_EqualityComparer(T) *spaceT(Collections_EqualityComparer,T,getDefault)() \
	{ \
		Collections_EqualityComparer(T) *defaultComparer = spaceT(Collections_EqualityComparer,T,s_defaultComparer); \
		if (defaultComparer == null) \
		{ \
			spaceT(Collections_EqualityComparer,T,s_defaultComparer) = defaultComparer = spaceT(Collections_EqualityComparer,T,CreateComparer)(); \
		} \
		return defaultComparer; \
	}

#endif /* __Collections_EqualityComparer_H__ */
